#region using

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

#endregion

namespace CodeDom
{
  internal class TemplateClassGenerator : TemplateTypeGenerator
  {
    public TemplateClassGenerator(Template template, CodeTypeReference[] baseTypes, TemplateNameGenerator nameGenerator) : base(template, baseTypes, nameGenerator)
    {
    }

    public override CodeTypeDeclaration Generate()
    {
      CodeTypeDeclaration typeDeclaration = GenerateTypeDeclaration(TypeAttributes.Class | TypeAttributes.Public);
      AddConstructor(typeDeclaration);
      AddFields(typeDeclaration);
      AddProperties(typeDeclaration);
      AddMethods(typeDeclaration);

      return typeDeclaration;
    }

    protected override CodeMemberProperty GenerateProperty(TemplateFieldGenerator field)
    {
      CodeMemberProperty property = base.GenerateProperty(field);
      string fieldName = _nameGenerator.GetFieldName(field.TemplateField, Name);
      CodeExpression fieldReference = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName);
      var assignmentStatement = new CodeAssignStatement(fieldReference, new CodePropertySetValueReferenceExpression());
      property.SetStatements.Add(assignmentStatement);
      property.GetStatements.Add(new CodeMethodReturnStatement(fieldReference));
      return property;                                          
    }

    protected override CodeTypeDeclaration GenerateTypeDeclaration(TypeAttributes typeAttributes)
    {
      CodeTypeDeclaration declaration = base.GenerateTypeDeclaration(typeAttributes);

      CodeAttributeDeclaration templateAttribute = new CodeAttributeDeclaration("BaseTemplates",
                                                                                new CodeAttributeArgument(
                                                                                  new CodePrimitiveExpression(
                                                                                    _template.ID.ToString())));
      declaration.CustomAttributes.Add(templateAttribute);

      return declaration;
    }

    protected override string GenerateTypeName()
    {
      return _nameGenerator.GetClassName(_template);
    }
  }
}